package fr.inserm.um915.bdibd.model;

import java.util.logging.Logger;

/**
 * 
 * DataExtractorFactoryIBDCount
 *
 */
public class DataExtractorFactoryIBDCount
	extends DataExtractorFactory
	{
	@SuppressWarnings("unused")
	private static final Logger LOG=Logger.getLogger("fr.inserm.um915.bdibd");
	private WhichIBD ibd_0_1_2;
	private boolean do_count;
	
	
	private abstract class AbstractDataExtractorIBD
		extends DataExtractorFactory.AbstractDataExtractor
		{
		boolean do_count;
		public abstract WhichIBD getWhichIBD();
		
		protected boolean isCounting()
			{
			return do_count;
			}
		protected abstract boolean accept(float ibd);
		@Override
		public Double getValue(LinkageRow linkageRow)
			{
			double value=0;
			for(Integer pairid:getPairOfIndividualIds())
				{
				float ibd=linkageRow.getIbd(pairid,this.getWhichIBD());
				if(accept(ibd))
					{
					if(isCounting())
						{
						value+=1.0;
						}
					else
						{
						if(this.getWhichIBD()==WhichIBD.USE_IBD_0)
							{
							ibd=1.0f-ibd;
							}
						value+=ibd;
						}
					}
				
				}
			return value;
			}
		}
	
	private class DataExtractorIBD0 extends AbstractDataExtractorIBD
		{
		@Override
		public WhichIBD getWhichIBD()
			{
			return WhichIBD.USE_IBD_0;
			}
		@Override
		protected boolean accept(float ibd) {
			return ibd < this.getTreshold();
			}
		}

	
	private abstract class DataExtractorNOTIBD0 extends AbstractDataExtractorIBD
		{
		@Override
		protected boolean accept(float ibd) {
			return ibd >= this.getTreshold();
			}
		}

	
	private class DataExtractorIBD1 extends DataExtractorNOTIBD0
		{
		@Override
		public WhichIBD getWhichIBD()
			{
			return WhichIBD.USE_IBD_1;
			}
		
		}
	
	private class DataExtractorIBD2 extends DataExtractorNOTIBD0
		{
		@Override
		public WhichIBD getWhichIBD()
			{
			return WhichIBD.USE_IBD_2;
			}
		}
	
	/** Constructor */
	public DataExtractorFactoryIBDCount(WhichIBD ibd_0_1_2,boolean count)
		{
		this.ibd_0_1_2=ibd_0_1_2;
		this.do_count=count;
		}
	
	DataExtractorFactoryIBDCount(DataExtractorFactoryIBDCount cp)
		{
		super(cp);
		this.ibd_0_1_2=cp.ibd_0_1_2;
		this.do_count=cp.do_count;
		}
	
	
	@Override
	public WhichIBD getWichIBD()
		{
		return ibd_0_1_2;
		}
	
	
	@Override
	public String getName()
		{
		return "IBD"+getWichIBD().ordinal()+" "+(do_count?"Count":"Sum");
		}
	@Override
	public String getDescription() {
		return getName()+" (p "+
			(getWichIBD()==WhichIBD.USE_IBD_0?"<":">= ")+getTreshold()+")";
		}
	
	public DataExtractor createDataExtractor()
		{
		AbstractDataExtractorIBD ex=null;
		switch(getWichIBD())
			{
			case USE_IBD_0: ex= new DataExtractorIBD0();break;
			case USE_IBD_1: ex= new DataExtractorIBD1();break;
			case USE_IBD_2: ex= new DataExtractorIBD2();break;
			default: throw new IllegalStateException();
			}
		ex.setModel(this.getModel());
		ex.setTransaction(this.getTransaction());
		ex.setTreshold(this.getTreshold());
		ex.do_count=this.do_count;
		return ex;
		}
	@Override
	public Object clone()
		{
		return new DataExtractorFactoryIBDCount(this);
		}
	}
